;西安科技大学--机械工程学院 训练题目
;三级题目
;由键盘输入任意字节数的A、B、C、D、E，
;按公式Y=A*B+C/D-E 计算 Y(n),将Y(n)按
;正负数分别存储于数据区BUF1和BUF2中,
;并将计算结果显示在屏幕上。
.model small,stdcall
.286
TRUE EQU -1
FALSE EQU 0
NULL EQU 0
ERROR_INPUT_STRING_NULL EQU 0EF01h
ERROR_INPUT_NOT_A_NUMBER EQU 0EF02h
ERROR_INPUT_NUMBER_OUT_RANGE EQU 0EF03h
ERROR_NEGATIVE_ZERO EQU 0EF04h
ERROR_DIVISOR_ZERO EQU 0EF05h
MaxBit EQU 3
iCount EQU 80
KEYBOARD STRUCT
    maxInput BYTE iCount
	inputCount BYTE ?
	buffer BYTE iCount DUP (?)
KEYBOARD ENDS

cCount EQU 5
C_ARRAY STRUCT
	variable_a WORD ?
	variable_b WORD ?
	variable_c WORD ?
	variable_d WORD ?
	variable_e WORD ?
	Result DWORD ?
C_ARRAY ENDS

input_NumString_to_8421BCD2HEX PROTO :WORD,:WORD
BCD2HEX PROTO :WORD
_printf PROTO :WORD
printf EQU invoke _printf,
_scanf PROTO :WORD
scanf EQU invoke _scanf,
calculator_Y PROTO :WORD
sInt2ASCII_String PROTO :WORD,:WORD,:WORD
clear_buf PROTO :WORD,:WORD
include Subproc.INC
.stack 200h
.data
	buf1 WORD cCount dup (?)
	buf2 WORD cCount dup (?)
b1Count WORD 0
b2Count WORD 0
	array_buf C_ARRAY cCount dup (<?,?,?,?,?,?>)
	KBbuf KEYBOARD <>
	negative_flag WORD FALSE
  	 buf BYTE 20 dup (?)
   buf0 BYTE 20 dup (?)
	tab_ BYTE 79 dup ('='),0dh,0ah,'$'
	msg0 BYTE "FATAL ERROR(0xFFFF):Unknown error!",0dh,0ah,'$'
	msg1 BYTE "Xi'an University of Science and Technoloy(xust)",0dh,0ah
	     BYTE "School of Mechanical Engineering(SoME)",0dh,0ah
	     BYTE "Assembly test Level.3",0dh,0ah,'$'
	msg2 BYTE "Yn=A*B+C/D-E",0dh,0ah
	     BYTE "1.Input ASCII signal decimal number to 8421BCD code",0dh,0ah
	     BYTE "2.Convert 8421BCD to HEX and saved memory array buf",0dh,0ah
	     BYTE "3.Calculate & ouput result",0dh,0ah,'$'
	msg3 BYTE "This program written By baidu\tieba\GuDaoTianHeng >-<",0dh,0ah
	     BYTE "Exit current process[Ctrl + Break]",0dh,0ah
	     BYTE "Please input different numbers(-999~999):",0dh,0ah,'$'
	msg4 BYTE "ERROR(0x0EF01):String NULL,Try again",0dh,0ah,'$'
	msg5 BYTE "ERROR(0x0EF02):Not a number,Try again",0dh,0ah,'$'
	msg6 BYTE "ERROR(0x0EF03):Number out range(-999~999),Try again",0dh,0ah,'$'
	msg7 BYTE "ERROR(0x0EF04):Negative zero(-0),Try again",0dh,0ah,'$'
	msg8 BYTE "Array group "
a_group BYTE ' ',0dh,0ah,'$'
   msg9 BYTE "Enter Variable "
 v_name BYTE ' :','$'
 cl_msg BYTE 40 dup (' '),0d,'$'
  msg10 BYTE "ERROR(0x0EF05):Divisor zero(i/0?),Try again",0dh,0ah,'$'
  msg11 BYTE "calculating.....................",'$'
  msg12 BYTE "OK",0dh,0ah,'$'
  CR_LF BYTE 0dh,0ah,'$'
  msg13 BYTE "Scale     Group(n)   [ Var A]*[ Var B]+[ Var C]/[ Var D]-[ Var E]=  Result Y(n)",0dh,0ah,'$'
  msg14 BYTE "Decimal   "
        BYTE "Group("
group_n BYTE ?,')',3 dup (' '),'('
  var_a BYTE 6 dup (' '),')*('
  var_b BYTE 6 dup (' '),')+('
  var_c BYTE 6 dup (' '),')/('
  var_d BYTE 6 dup (' '),')-('
  var_e BYTE 6 dup (' '),')='
        BYTE 3 dup (' ')
ResultY BYTE 4 dup (' ')
Results BYTE 6 dup (' '),0dh,0ah,'$'
.CODE
START:
	mov ax,@data
	mov ds,ax
	mov es,ax
	printf ADDR msg1
	printf ADDR tab_
	printf ADDR msg2
	printf ADDR tab_
	printf ADDR msg3
	xor cx,cx
	xor bx,bx
	.while bx < cCount
		mov al,'1'
		add al,bl
		mov a_group,al
		printf ADDR msg8
		mov ax,TYPE C_ARRAY
		mul bx
		lea dx,array_buf.variable_a
		add dx,ax
		L1:
		push bx
		push cx
		@@:
		mov al,'a'
		add al,cl
		
;If you need dump register,don't comment and continue execute.
;		push ax
;		push dx
;		push di
;		mov dl,cl
;		lea di,buf0
;		mov WORD ptr ds:[di],"lc"
;		mov BYTE ptr ds:[di+2],':'
;		add di,3
;		call RHEX2ASCII
;		mov WORD ptr ds:[di+2],"$ "
;		printf ADDR buf0
;		
;		mov dl,bl
;		lea di,buf1
;		mov WORD ptr ds:[di],"lb"
;		mov BYTE ptr ds:[di+2],':'
;		add di,3
;		call RHEX2ASCII
;		mov WORD ptr ds:[di+5],0a0dh
;		mov BYTE ptr ds:[di+7],'$'
;		printf ADDR buf1
;		pop di
;		pop dx
;		pop ax

		mov v_name,al
		printf ADDR msg9
		scanf ADDR KBbuf
		printf ADDR CR_LF
		invoke input_NumString_to_8421BCD2HEX,ADDR KBbuf,dx
		.if ax != 0
			.if ax == ERROR_INPUT_STRING_NULL
				printf ADDR msg4
				jmp @b
			.elseif ax == ERROR_INPUT_NOT_A_NUMBER
				printf ADDR msg5
				jmp @b
			.elseif ax == ERROR_INPUT_NUMBER_OUT_RANGE
				printf ADDR msg6
				jmp @b
			.elseif ax == ERROR_NEGATIVE_ZERO
				printf ADDR msg7
				jmp @b
			.else
				printf ADDR msg0
				jmp _exit
			.endif
		.endif
		.if cx == 3
			push bx
			mov bx,dx
			mov ax,ds:[bx]
			pop bx
			.if ax == 0
				mov ax,ERROR_DIVISOR_ZERO
				printf ADDR msg10
				jmp @b
			.endif
		.endif
		pop cx
		pop bx
		add dx,2
		inc cx
		.if cx >= 5
			inc bx
			xor cx,cx
		.else
			jmp L1
		.endif
	.endw
	
	printf ADDR msg11
	xor cx,cx
	.while cx < cCount
	lea bx,array_buf
	mov ax,TYPE C_ARRAY
	mul cx
	add bx,ax
	invoke calculator_Y,bx
	inc cx
	.endw
	printf ADDR msg12
	printf ADDR tab_
	printf ADDR msg13
	
	mov cx,0
	.while cx < cCount
		push cx
		mov ax,TYPE C_ARRAY
		mul cx
		mov bp,ax
		lea si,array_buf
		xor dx,dx
		mov ax,WORD ptr ds:(C_ARRAY ptr [si+bp]).variable_a
		invoke sInt2ASCII_String,ADDR var_a,ADDR buf,ADDR buf0
		xor dx,dx
		mov ax,WORD ptr ds:(C_ARRAY ptr [si+bp]).variable_b
		invoke sInt2ASCII_String,ADDR var_b,ADDR buf,ADDR buf0
		xor dx,dx
		mov ax,WORD ptr ds:(C_ARRAY ptr [si+bp]).variable_c
		invoke sInt2ASCII_String,ADDR var_c,ADDR buf,ADDR buf0
		xor dx,dx
		mov ax,WORD ptr ds:(C_ARRAY ptr [si+bp]).variable_d
		invoke sInt2ASCII_String,ADDR var_d,ADDR buf,ADDR buf0
		xor dx,dx
		mov ax,WORD ptr ds:(C_ARRAY ptr [si+bp]).variable_e
		invoke sInt2ASCII_String,ADDR var_e,ADDR buf,ADDR buf0
		mov dx,WORD ptr ds:(C_ARRAY ptr [si+bp]).Result+2
		mov ax,WORD ptr ds:(C_ARRAY ptr [si+bp]).Result
		test ax,01000000000000000b
		jz positive
		Negative:
		lea di,buf2
		add di,b2Count
		mov WORD ptr [di],ax
		add b2Count,size WORD
		jmp @f
		positive:
		lea di,buf1
		add di,b1Count
		mov WORD ptr [di],ax
		add b1Count,size WORD
		@@:
		invoke clear_buf,ADDR ResultY,10
		.if dx !=0
			invoke sInt2ASCII_String,ADDR ResultY,ADDR buf,ADDR buf0
		.else
			invoke sInt2ASCII_String,ADDR Results,ADDR buf,ADDR buf0
		.endif
		pop cx
		inc cx
		mov al,'0'
		add al,cl
		mov group_n,al
		printf ADDR msg14
	.endw
	printf ADDR tab_
	_exit:
	xor al,al
	mov ah,4ch     ;结束,可以修改al设置返回码
	int 21h
	
END START